package tcp

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"net"
	"time"
)

func StartEchoServer() {

	startTcpServer(echoHandle2, "127.0.0.1", 20000)
}

//这个方法，有粘包的问题。
func echoHandle(conn net.Conn) {

	defer conn.Close()
	for {
		var buf [128]byte
		n, err := conn.Read(buf[:])
		if n == 0 || err == io.EOF {
			return
		}
		if err != nil {
			fmt.Printf("read from connect failed, err: %v\n", err)
			return
		}
		fmt.Printf("receive from client, data: %v\n", string(buf[:n]))
		//发送数据
		if _, err = conn.Write([]byte("Send From Server")); err != nil {
			fmt.Printf("write to client failed, err: %v\n", err)
			break
		}
	}
}

// 这个方法，包前4个字节来表示数据的长度来处理粘包
func echoHandle2(conn net.Conn) {

	defer conn.Close()
	for {
		reader := bufio.NewReader(conn)
		for {
			peek, err := reader.Peek(4)
			if err != nil {
				if err != io.EOF {
					log.Println("tcp server error :", err)
				} else {
					break
				}
			}
			buf := bytes.NewBuffer(peek)
			var len int32
			err = binary.Read(buf, binary.BigEndian, &len)
			if err != nil {
				log.Println("tcp server read buf error,", err)
			}
			//缓冲区读到的数据还不够
			if int32(reader.Buffered()) < len+4 {
				continue
			}
			data := make([]byte, len+4)
			_, err = reader.Read(data)
			if err != nil {
				continue
			}
			log.Println("server received msg :", string(data[4:]))
		}
	}
}

func echo(c net.Conn, shout string, delay time.Duration) {

	i := 0
	for {
		i++
		if i > 20 {
			fmt.Fprint(c, "\r", shout)
			break
		}
		for _, r := range `-\|/` {
			fmt.Fprint(c, "\r", string(r), shout)
			time.Sleep(delay)
		}
	}
}

func echoComplexHandleConn(c net.Conn) {
	defer closeConn(c)
	input := bufio.NewScanner(c)
	for input.Scan() {
		echo(c, input.Text(), 100*time.Millisecond)
	}
}

var goroutineDown = make(chan struct{})

//goroutine怎么退出呢？一般用关闭channel来广播退出
func canceled() bool {
	select {
	case <-goroutineDown:
		return true
	default:
		return false
	}
}
